專案資料夾跟 Python 虛擬環境都準備好。現在要處理一件專案越做越大就會越重要的事情,版本控制。想像一下,你今天修改了一段 Code,跑得很好,明天又覺得:「這裡好像可以再改一下。」結果一改,壞掉了。這時候你突然想:「昨天那版明明可以跑,我要怎麼回去?」如果完全沒有版本紀錄,你可能只能開始找:
main.py
main_final.py
main_final2.py
main_final_真的最後一版.py
所以我們需要 Git。
先釐清一個很容易混在一起的概念:
**Git **是版本控制工具。可以記錄你的 Code 每一次修改了什麼,就算沒有網路,也可以在自己的電腦上使用。
GitHub 是放 Git Repository 的遠端平台。可以把這些版本紀錄放到遠端,方便備份、協作、Code Review,也讓未來想看這個作品集的人可以直接看到你的專案。
還沒有 GitHub 帳號的朋友,可以先到 GitHub 建立一個帳號。登入之後,在 GitHub 左上角找到 New repository,建立一個新的 Repo( 簡稱),可以先把它想成一個專門存放這個專案與版本紀錄的倉庫。
這個專案我使用MRT_project 作為 Repo 名稱。如果你的本機已經像上一篇一樣建立好 README.md、專案資料夾等內容,建議建立 Repo 時先不要另外初始化 README、.gitignore 或 License,避免本機和遠端一開始就出現兩套不同的版本。
建立完成後,GitHub 會提供 Repository URL,等等我們要把本機專案和這個遠端 Repository 接起來。
回到 VS Code Terminal,確認目前的位置是在專案根目錄,接著執行:
git init #讓 Git 開始管理這個資料夾
git branch -M main #把這個專案的主要版本命名為 main。
git commit --allow-empty -m "Initialize repository" #先建立一筆初始紀錄,即使目前還沒有檔案要提交也沒關係。
git remote add origin <你的 GitHub Repository URL> #告訴 Git「這個專案在 GitHub 上的位置在哪裡」。
# 這裡的 origin 只是 Git 通常用來稱呼主要遠端 Repository 的名稱。
git remote -v #確認遠端位置有沒有設定成功。
git push -u origin main #把剛剛建立的 main 上傳到 GitHub。
其中 <你的 GitHub Repository URL> 要換成你剛剛在 GitHub 建立 Repository 後取得的網址。
說到版本控制,接著會出現另一個問題:所有檔案都應該交給 Git 管嗎? No~~~。
像上一篇建立的 .venv/,裡面有大量只屬於這台電腦與目前 Python 環境的檔案,不需要上傳。另一個常見檔案 .env,通常會保存 API Key、密碼或其他環境設定,更不應該直接提交到 GitHub。所以我們會在專案根目錄建立 .gitignore,告訴 Git:「這些東西不要控管。」例如:
.venv/ # 本機的 Python 虛擬環境,不需要上傳。
.env # 可能包含 API Key、密碼等敏感資料,不應上傳。
__pycache__/ # Python 自動產生的暫存檔,不需要上傳。
之後如果有新的敏感資料或不需要進入版本控制的檔案,再繼續加入 .gitignore。 而且 .gitignore 最好在第一次 git add 之前就設定好,避免不該提交的檔案不小心先被 Git 追蹤。
你可以把分支(Branch) 想成「專案的另一條修改路線」。假設目前 main 裡放的是可以正常使用的專案版本。今天我們想新增或修改一些東西,但又不想直接動到 main,就可以先開一個新的 Branch,在裡面工作。等 init 裡面的修改都完成、確認沒問題之後,再把它合併回 main。這樣做的好處是修改過程和主要版本可以先分開,不會一邊改東西,一邊直接影響 main。
main ← 目前主要版本
│
└── init ← 從 main 開出來的新分支,在這裡進行修改
# 這個專案中,我們先從 main 建立一個叫做 init 的 Branch
git switch -c init # 建立一個叫 init 的新分支,然後切換過去。
git branch #確認目前位置,前面有*的就是正在使用的 branch。
你可以把建立版本想成三個步驟,修改檔案->git add->把這次想保存的檔案挑出來->git commit 正式保存成一個版本。Git 不會因為你修改檔案就自動幫你建立版本。它大概會經過以下的流程:
Working Directory(你目前正在修改的檔案。)
↓
git add .
↓
Staging Area (準備放進下一個版本的檔案。)
↓
git commit (真正保存下來的一個版本紀錄。)
↓
Local Repository
現在我們要把 Day 2 建立的專案內容保存成一個版本:
git status # 先看看目前有哪些檔案被新增或修改。如果已經變更,檔案名稱會是紅色
git add . # "."代表把目前目錄下符合條件的修改加入 Staging Area(暫存區)
git status # 再檢查一次,確認等等有哪些檔案會被保存。檔案名稱會變成綠色
git commit -m "Initialize project structure" # 把這些內容正式保存成一個 Git 版本。 -m 表示message 這次commit 說明
git push -u origin init # 把電腦上的 init Branch 上傳到 GitHub。
這裡要特別注意:Push ≠ Merge。git push 只是把本機 init branch 的 commit 傳到 GitHub。現在 GitHub 上可能會同時存在 main /init 但是 main 還沒有得到 init 的修改。
這時候進入 GitHub,就可以建立 Pull Request(PR)。Pull Request 可以理解成「我這條 branch 已經改好了,請檢查這些修改,確認之後把它合併進 main。」建立 PR 之後,可以先查看 Files changed,確認到底有哪些檔案被新增、刪除或修改。沒有問題之後,再執行 Merge。這時候遠端 GitHub 的init 併入main,才真正完成合併。
gh pr create --title " xxxx" --body "xxxx"
gh pr merge #確認 PR 沒問題後,把它合併進 main。
但是還有最後一件事情。GitHub 上的 main 已經更新了,你的電腦還不知道,所以要切回 main,把 GitHub 上最新的 main 拉回本機:
git switch main # 切回本機的 main Branch。
git pull origin main #把 GitHub 上最新的 main 下載並同步到本機。
git status
如果看到 working tree clean,代表目前沒有尚未處理的修改。到這裡,我們就完成了這次 Stage 0 的 Git workflow:
建立 Branch
↓
修改檔案
↓
git add
↓
git commit
↓
git push
↓
GitHub Pull Request
↓
Merge into main
↓
本機切回 main
↓
git pull
到這裡,我們已經有:
專案結構 → Python 虛擬環境 → Dependencies → Git 版本控制 → GitHub Repository
這些東西看起來不像 Data Pipeline 本身,卻是在後面專案越來越複雜時,幫助我們保持環境、程式碼與版本可管理的基礎。下一個 Stage,我們終於要正式碰資料了。
下一篇:Day 4|Stage 1(1/2):拿到資料先別急著清洗,從資料粒度(Grain)開始做